<template>
  <div class="table" :class="{ table_moving: dragState.dragging }">
    <el-table
      id="iTable"
      ref="multipleTable"
      v-loading="loading"
      :show-summary="options.summary"
      :summary-method="getSummaries"
      :cell-class-name="cellClassName"
      :row-class-name="rowClass"
      :row-style="tableRowStyle"
      :cell-style="handleCellStyle"
      :class="tableClass"
      :data="list"
      :stripe="options.stripe || true"
      :border="options.border || true"
      :highlight-current-row="options.highlightCurrentRow"
      :lazy="options.lazy"
      :load="loadGetData"
      style="width: 100%"
      :row-key="(row) => getRowKey(row)"
      :fit="true"
      :height="options.pageMove ? options.height : autoHeight"
      :max-height="!options.noMaxHeight ? autoHeight : null"
      :default-expand-all="options.defaultExpandAll"
      :header-cell-class-name="headerCellClassName"
      :span-method="options.isSpanMethod ? objectSpanMethod : null"
      :tree-props="options.treeProps"
      :expand-row-keys="expandRowKeys"
      @row-click="clickRow"
      @cell-click="cellClick"
      @row-dblclick="dblclickRow"
      @row-contextmenu="contextmenu"
      @header-click="headClick"
      @header-contextmenu="headcontextmenu"
      @select="select"
      @select-all="selectAll"
      @current-change="rowChange"
      @selection-change="handleSelectionChange"
      @contextmenu.prevent.native="openMenu($event)"
      @onClearSelection="onClearSelection"
      @expand-change="expandRow"
      @sort-change="handleSortChange"
    >
      <!-- <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width">
        <template slot-scope="{row,$index}">
          <el-button type="primary" size="mini" @click="handleUpdate(row)">
            {{ $t('table.edit') }}
          </el-button>
        </template>
      </el-table-column> -->
      <!--region 数据列-->
      <!--开启展开行-->
      <el-table-column v-if="options.tableExpand" type="expand">
        <template slot-scope="{ row, $index }">
          <slot name="expandSlot" :rowInfo="row" :index="$index" />
        </template>
      </el-table-column>
      <el-table-column
        v-if="options.rowDrag"
        align="center"
        label="拖拽"
        width="80"
      >
        <svg-icon class="drag-handler" icon-class="drag" />
      </el-table-column>
      <!-- <slot name="fixed" /> -->
      <template v-for="(column, index) in tableHeader" :key="column.id">
        <!--复选框（START）-->
        <el-table-column
          v-if="column.type == 'selection'"
          :key="column.id"
          type="selection"
          :width="column.width ? column.width : 50"
          :align="column.align ? column.align : 'center'"
          :fixed="column.fixed"
          :selectable="column.selectable"
          :reserve-selection="column.reserve"
        />
        <!--复选框（END）-->

        <!--序号（START）-->
        <el-table-column
          v-else-if="column.type == 'index'"
          type="index"
          :label="column.label ? column.label : '序号'"
          :width="column.width ? column.width : 80"
          :align="column.align ? column.align : 'center'"
          :column-key="index.toString()"
          :fixed="column.fixed"
        />
        <!--序号（END）-->

        <!--input编辑-->
        <el-table-column
          v-else-if="column.type == 'input'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :width="column.width"
          :fixed="column.fixed"
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <template
              v-if="
                scope.row.id === cellClickIndex &&
                cellClickLabel === column.label
              "
            >
              <!-- 根据noEditInfo判断 不可编辑 -->
              <template
                v-if="column.noEditInfoFun && column.noEditInfoFun(scope.row)"
              >
                <span>{{ scope.row[column.field] }}</span>
              </template>
              <div v-else class="editBox">
                <el-input
                  v-model="scope.row[column.field]"
                  maxlength="300"
                  placeholder="请输入"
                  size="mini"
                  @keyup.enter.native="saveRow(scope, column.callback)"
                />
                <i
                  v-if="!column.notShowSave"
                  slot="suffix"
                  class="el-icon-circle-check el-input__icon"
                  @click="saveRow(scope, column.callback)"
                />
                <i
                  slot="suffix"
                  class="el-icon-circle-close el-input__icon"
                  @click="clearRow(scope)"
                />
              </div>
            </template>

            <template v-else>
              <span>{{ scope.row[column.field] }}</span>
            </template>
          </template>
        </el-table-column>
        <!-- inputNumber -->
        <el-table-column
          v-else-if="column.type == 'inputNumber'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :fixed="column.fixed"
          :width="column.width"
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <!-- 不可修改 编辑 -->
            <template
              v-if="column.noEditInfoFun && column.noEditInfoFun(scope.row)"
            >
              <!-- 有render函数 -->
              <expandDom
                v-if="column.render"
                :column="column"
                :row="scope.row"
                :render="column.render"
                :index="index"
              />
              <!-- 没有render函数 -->
              <span v-else>{{ scope.row[column.field] }}</span>
            </template>
            <template
              v-else-if="
                scope.row.id === cellClickIndex &&
                cellClickLabel === column.label
              "
            >
              <div class="editBox">
                <el-input-number
                  v-model="scope.row[column.field]"
                  :min="column.min || 0"
                  :max="
                    column.maxValFun
                      ? inputNumberMaxValFun(scope, column.maxValFun)
                      : column.max || null
                  "
                  placeholder="请输入"
                  size="mini"
                  @change="saveRow(scope, column.callback)"
                  @blur="blurRow(scope, column.callback)"
                />
                <i
                  v-if="!column.notShowSave"
                  slot="suffix"
                  class="el-icon-circle-check el-input__icon"
                  @click="saveRow(scope, column.callback)"
                />
                <i
                  v-if="!column.notShowClear"
                  slot="suffix"
                  class="el-icon-circle-close el-input__icon"
                  @click="clearRow(scope)"
                />
              </div>
            </template>
            <template v-else>
              <span
                >{{ scope.row[column.field] }}
                {{ column.fieldTip && column.fieldTip }}</span
              >
            </template>
          </template>
        </el-table-column>
        <!-- switch -->
        <el-table-column
          v-else-if="column.type == 'switch'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :fixed="column.fixed"
          :width="column.width"
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row[column.field]"
              :active-text="column.activeText"
              :inactive-text="column.inactiveText"
              @change="
                column.switchChange && switchChange(scope, column.switchChange)
              "
            />
          </template>
        </el-table-column>

        <!-- textarea -->
        <el-table-column
          v-else-if="column.type == 'textarea'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :width="column.width"
          :fixed="column.fixed"
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <!-- 不可修改 编辑 -->
            <template
              v-if="column.noEditInfoFun && column.noEditInfoFun(scope.row)"
            >
              <!-- 有render函数 -->
              <expandDom
                v-if="column.render"
                :column="column"
                :row="scope.row"
                :render="column.render"
                :index="index"
              />
              <!-- 没有render函数 -->
              <span v-else>{{ scope.row[column.field] }}</span>
            </template>
            <template
              v-else-if="
                scope.row.id === cellClickIndex &&
                cellClickLabel === column.label
              "
            >
              <div class="editBox">
                <el-input
                  v-model="scope.row[column.field]"
                  placeholder="请输入"
                  size="mini"
                  type="textarea"
                  @blur="blurRow(scope, column.callback)"
                />
                <i
                  v-if="!column.notShowSave"
                  slot="suffix"
                  class="el-icon-circle-check el-input__icon"
                  @click="saveRow(scope, column.callback)"
                />
                <i
                  v-if="!column.notShowClear"
                  slot="suffix"
                  class="el-icon-circle-close el-input__icon"
                  @click="clearRow(scope)"
                />
              </div>
            </template>
            <template v-else>
              <span
                >{{ scope.row[column.field] }}
                {{ column.fieldTip && column.fieldTip }}</span
              >
            </template>
          </template>
        </el-table-column>

        <!-- cascader -->
        <el-table-column
          v-else-if="column.type == 'cascader'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :fixed="column.fixed"
          :width="column.width"
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <template
              v-if="
                scope.row.id === cellClickIndex &&
                cellClickLabel === column.label
              "
            >
              <!-- 根据noEditInfo判断 不可编辑 -->
              <template
                v-if="column.noEditInfoFun && column.noEditInfoFun(scope.row)"
              >
                <span>{{ scope.row[column.field] }}</span>
              </template>
              <div v-else>
                <el-cascader
                  v-model="scope.row[column.field]"
                  :options="column.typeOptions"
                  :props="{ emitPath: false }"
                />
                <i
                  v-if="!column.notShowSave"
                  slot="suffix"
                  class="el-icon-circle-check el-input__icon"
                  @click="saveRow(scope, column.callback)"
                />
                <i
                  slot="suffix"
                  class="el-icon-circle-close el-input__icon"
                  @click="clearRow(scope)"
                />
              </div>
            </template>
            <template v-else>
              <template
                v-for="(typeOption, typeOptionIndex) in column.typeOptions"
              >
                <template
                  v-for="(fieldOption, fieldIndex) in typeOption.children"
                >
                  <span
                    v-if="fieldOption.value == scope.row[column.field]"
                    :key="fieldIndex + typeOptionIndex * 2"
                    >{{ fieldOption.label }}</span
                  >
                </template>
              </template>
            </template>
          </template>
        </el-table-column>
        <!--select选择框-->
        <el-table-column
          v-else-if="column.type == 'select'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :width="column.width"
          :fixed="column.fixed"
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <template
              v-if="
                scope.row.id === cellClickIndex &&
                cellClickLabel === column.label
              "
            >
              <!-- 根据noEditInfo判断 不可编辑 -->
              <template
                v-if="column.noEditInfoFun && column.noEditInfoFun(scope.row)"
              >
                <span>{{ scope.row[column.field] }}</span>
              </template>
              <div v-else class="editBox">
                <div @click.stop>
                  <el-select
                    :ref="'columnSelect' + column.field + scope.row.id"
                    v-model="scope.row[column.field]"
                    placeholder="请选择"
                    filterable
                    :multiple="column.isMultiple"
                    @visible-change="
                      chooseCustom(
                        $event,
                        column.isMultiple,
                        column.callback,
                        scope.row
                      )
                    "
                    @change="selectChange(column, scope.row)"
                  >
                    <el-option
                      v-for="item in column.typeOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </div>
                <i
                  v-if="!column.notShowSave"
                  slot="suffix"
                  class="el-icon-circle-check el-input__icon"
                  @click="
                    saveRow(scope, column.callback, scope.row[column.field])
                  "
                />
                <i
                  slot="suffix"
                  class="el-icon-circle-close el-input__icon"
                  @click="clearRow(scope)"
                />
              </div>
            </template>
            <template v-else>
              <!-- 多选的显示 -->
              <template v-if="column.isMultiple">
                <span>{{
                  transform(column.typeOptions, scope.row[column.field])
                }}</span>
                <!-- 单选的显示 -->
              </template>

              <template v-else>
                <template v-for="(typeOption, index3) in column.typeOptions">
                  <span
                    v-if="scope.row[column.field] == typeOption.value"
                    :key="index3"
                    >{{ typeOption.label }}</span
                  >
                </template>
              </template>
            </template>
          </template>
        </el-table-column>
        <!-- slot 添加自定义配置项 -->
        <!-- <slot v-else-if="column.slot" :name="column.slot" :tit="index" /> -->

        <slot v-else-if="column.slot" :name="column.slot" :tit="index" />
        <!-- 图片和pdf -->
        <!-- xlsx  docx -->
        <el-table-column
          v-else-if="column.type == 'file'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :width="
            !column.isWidth
              ? column.width
              : flexColumnWidth(column.field, list, column.width)
          "
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :fixed="column.fixed"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <span
              v-for="(item, fIndex) in scope.row[column.field]"
              :key="fIndex"
              style="cursor: pointer"
              @click="openFilePreviewPage(scope.row[column.field])"
            >
              <template
                v-if="
                  item.name.substr(item.name.lastIndexOf('.') + 1) === 'xlsx'
                "
              >
                <!-- xlsx -->
                <img
                  slot="reference"
                  src="~@/assets/xlsx.png"
                  :alt="item.name"
                  :title="item.name"
                  style="
                    max-height: 20px;
                    max-width: 70px;
                    padding-right: 5px;
                    vertical-align: middle;
                  "
                />
              </template>
              <template
                v-else-if="
                  item.name.substr(item.name.lastIndexOf('.') + 1) === 'docx'
                "
              >
                <!-- docx -->
                <img
                  slot="reference"
                  src="~@/assets/word.png"
                  :alt="item.name"
                  :title="item.name"
                  style="
                    max-height: 20px;
                    max-width: 70px;
                    padding-right: 5px;
                    vertical-align: middle;
                  "
                />
              </template>
              <template
                v-else-if="
                  item.name.substr(item.name.lastIndexOf('.') + 1) === 'pdf'
                "
              >
                <!-- pdf -->
                <img
                  slot="reference"
                  src="~@/assets/file-pdf-fill.png"
                  :alt="item.name"
                  :title="item.name"
                  style="
                    max-height: 20px;
                    max-width: 70px;
                    padding-right: 5px;
                    vertical-align: middle;
                  "
                />
              </template>
              <template v-else>
                <!-- img -->
                <!-- 图片的完整路径暂时不显示 -->
                <img
                  slot="reference"
                  :src="item.url"
                  style="
                    max-height: 25px;
                    max-width: 70px;
                    padding-right: 5px;
                    vertical-align: middle;
                  "
                />
              </template>
            </span>
          </template>
        </el-table-column>
        <!-- 二维码-->
        <el-table-column
          v-else-if="column.type == 'qrCode'"
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :width="
            !column.isWidth
              ? column.width
              : flexColumnWidth(column.field, list, column.width)
          "
          :sortable="column.sort"
          :fixed="column.fixed"
          :column-key="index.toString()"
        >
          <template slot-scope="scope">
            <div style="margin: 10px">
              <!-- <TisQrCode2Create
                :id="`qrCode_${scope.row.id}`"
                :text="scope.row[column.field]"
                :height="48"
                :width="48"
              /> -->
            </div>
          </template>
        </el-table-column>

        <!-- 默认渲染列-渲染每一列的汉字 -->
        <el-table-column
          v-else
          :prop="column.field"
          :label="column.label"
          :align="column.align"
          :width="
            !column.isWidth
              ? column.width
              : flexColumnWidth(column.field, list, column.width)
          "
          :show-overflow-tooltip="true"
          :sortable="column.sort"
          :fixed="column.fixed"
          :column-key="index.toString()"
          :sort-method="(a, b) => sortMethodColumn(a, b, column)"
        >
          <template v-slot:header>
            <span class="header-ellipsis">{{ column.label }}</span>
          </template>
          <template #default="{ row, $index }">
            <!--正常渲染-->
            <template v-if="!column.render">
              <template v-if="column.formatter">
                <span v-html="column.formatter(scope.row, column)" />
              </template>
              <template v-else>
                <span>{{ row[column.field] }}</span>
              </template>
            </template>
            <!--render函数-->
            <template v-else>
              <expandDom
                :column="column"
                :row="scope.row"
                :render="column.render"
                :index="index"
              />
            </template>
          </template>
          <!--todo://需要修改-->
        </el-table-column>
      </template>
    </el-table>
    <ul
      v-show="visible"
      :style="{ left: left + 'px', top: top + 'px' }"
      class="contextClickmenu"
    >
      <li @click="exportExcel">导出当前页</li>
      <li @click="copyCurrentCell">复制当前单元格</li>
    </ul>
  </div>
</template>

<script>
// import {
//   mapState
// } from 'vuex'
import { parseTime } from "@/utils/ruoyi";
import Sortable from "sortablejs";
export default {
  components: {
    /**
     * render函数渲染组件
     */
    expandDom: {
      functional: true,
      props: {
        row: Object,
        render: Function,
        index: Number,
        column: {
          type: Object,
          default: null,
        },
      },
      render: (h, ctx) => {
        const params = {
          row: ctx.props.row,
          index: ctx.props.index,
        };
        if (ctx.props.column) {
          params.column = ctx.props.column;
        }
        return ctx.props.render(h, params);
      },
    },
  },
  props: {
    // 数据列表
    list: {
      type: Array,
      default: () => [],
    },
    // 需要展示的列 == prop, 列对应属性, label: 列名, align: 对齐方式, width: 列宽 noEditInfoFun: 禁止修改的判断函数
    columns: {
      type: Array,
      default: () => [],
    },
    options: {
      type: Object,
      default: function () {
        return {
          height: "100%", // 默认高度-为了表头固定
          stripe: true, // 是否为斑马纹
          highlightCurrentRow: true, // 是否需要高亮当前行
          border: true, // 是否有纵向边
          lazy: true, // 是否需要懒加载
          rowDrag: false, // 行拖拽
          fixed: true,
          rowKey: "id",
          // loading: false // 是否需要等待效果
        };
      },
    },
    loading: {
      type: Boolean,
      default: false,
    },
    tableClass: {
      type: String,
      default: "hxTable",
    },
    tableRowStyle: {
      type: Function,
      default: () => {
        return { height: "35px" };
      },
    }, // 行样式
    tableRowClass: {
      type: Function,
      default: () => {
        return "";
      },
    }, // 行样式
    expandRowKeys: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      selectRow: [], // 选中的行
      tableHeader: this.columns, // 保存头部数据为了拖拽
      multipleSelection: [], // 多行选中
      visible: false,
      top: 0,
      left: 0,
      cellClickIndex: null, // 点击的单元格
      cellClickLabel: "", // 当前点击的列名
      tempRow: "", // 缓存临时数据
      cellField: "", // 缓存的列
      getIndex: "",
      autoHeight: parseInt(window.innerHeight) - 220 + "px", // 动态高度
      oldList: [], // 旧数据
      newList: [], // 新数据
      dragState: {
        start: -9, // 起始元素的 index
        end: -9, // 移动鼠标时所覆盖的元素 index
        dragging: false, // 是否正在拖动
        direction: undefined, // 拖动方向
      },
      currentCellText: "", // 当前点击的单元格的内容
    };
  },
  // computed: {
  //   ...mapState({
  //     sidebar: state => state.app.sidebar,
  //     device: state => state.app.device
  //   })
  // },
  watch: {
    visible(value) {
      if (value) {
        document.body.addEventListener("click", this.closeMenu);
      } else {
        document.body.removeEventListener("click", this.closeMenu);
      }
    },
    // 监听多选的选择状态、数据
    multipleSelection(data) {
      this.selectRow = [];
      if (data.length > 0) {
        data.forEach((item, index) => {
          this.selectRow.push(this.list.indexOf(item));
        });
      }
    },
    columns(val, oldVal) {
      this.tableHeader = val;
    },
  },
  mounted() {
    // 监听页面刷新和关闭事件
    window.addEventListener("beforeunload", (e) => this.cacheColumns());
    document.body.ondrop = function (event) {
      event.preventDefault();
      event.stopPropagation();
    };
    this.$nextTick(() => {
      // 根据浏览器高度设置初始高度
      // if (this.currentPageOpenType === 'unLoad') {

      //  this.autoHeight = window.innerHeight - this.$refs.multipleTable.$el.offsetTop - 10
      // } else {
      //   this.autoHeight = window.innerHeight - this.$refs.multipleTable.$el.offsetTop - 188
      // }
      // // this.autoHeight = window.innerHeight - this.$refs.multipleTable.$el.offsetTop - 400
      // 监听浏览器高度变化，改变表格高度
      window.onresize = () => {
        this.autoHeight = parseInt(window.innerHeight) - 220 + "px";
      };
      if (this.options.rowDrag) {
        this.setSort();
      }
      // this.columnDrop()
    });
  },
  // 统计数据不显示问题(不知道为什么需要这个)
  updated() {
    this.$nextTick(() => {
      this.$refs["multipleTable"].doLayout();
    });
  },
  created() {},
  deactivated() {
    // 离开组件时执行 只有在<keep-alive></keep-alive>包裹的时候才有效
    // 有tableColumnsCacheKey 进行存储Columns
    window.removeEventListener("beforeunload", this.cacheColumns());
    this.cacheColumns();
  },
  destroyed() {
    window.removeEventListener("beforeunload", this.cacheColumns());
    // 组件销毁时
    this.cacheColumns();
  },
  methods: {
    getRowKey(row) {
      if (this.options.rowKey) {
        return row[this.options.rowKey];
      } else {
        return row.id;
      }
    },
    /**
     * @description: 列排序
     * @param {*} before
     * @param {*} after
     * @param {*} column
     */
    sortMethodColumn(before, after, column) {
      if (column.sortMethod) {
        column.sortMethod();
      } else {
        if (before[column.field]) {
          // 汉字排序
          if (/[\u4e00-\u9fa5]/.test(before[column.field])) {
            return before[column.field].localeCompare(
              after[column.field],
              "zh"
            );
          } else {
            // 数字排序
            if (Number.isFinite(before[column.field])) {
              return before[column.field] - after[column.field];
            } else {
              return before[column.field].localeCompare(
                after[column.field],
                "en-u-kn-true"
              );
            }
          }
        }
      }
    },
    /**
     * @description: 缓存column
     */
    cacheColumns() {
      if (this.options.tableColumnsCacheKey) {
        // 要存储的column的Fields标识
        const tableHeaderFields = [];
        this.tableHeader.filter((h) => h.field && tableHeaderFields.push(h));
        const columnsObject = JSON.stringify({
          initFields: tableHeaderFields,
        });
        localStorage.setItem(this.options.tableColumnsCacheKey, columnsObject);
      }
    },
    // 自适应表格列宽
    flexColumnWidth(str, tableData, width, flag = "max") {
      // str为该列的字段名(传字符串);tableData为该表格的数据源(传变量);
      // flag为可选值，可不传该参数,传参时可选'max'或'equal',默认为'max'
      // flag为'max'则设置列宽适配该列中最长的内容,flag为'equal'则设置列宽适配该列中第一行内容的长度。
      str = str + "";
      let columnContent = "";
      if (
        !tableData ||
        !tableData.length ||
        tableData.length === 0 ||
        tableData === undefined
      ) {
        return width + "px";
      }
      if (!str || !str.length || str.length === 0 || str === undefined) {
        return width + "px";
      }
      if (flag === "max") {
        // 获取该列中最长的数据(内容)
        for (let i = 0; i < tableData.length; i++) {
          if (tableData[i][str] !== null) {
            columnContent = tableData[i][str];
          }
        }
      }
      // 以下分配的单位长度可根据实际需求进行调整
      let flexWidth = 0;
      for (const char of columnContent) {
        if ((char >= "A" && char <= "Z") || (char >= "a" && char <= "z")) {
          // 如果是英文字符，为字符分配8个单位宽度
          flexWidth += 15;
        } else if (char >= "\u4e00" && char <= "\u9fa5") {
          // 如果是中文字符，为字符分配15个单位宽度
          flexWidth += 30;
        } else {
          // 其他种类字符，为字符分配8个单位宽度
          flexWidth += 15;
        }
      }
      if (flexWidth < 100) {
        // 设置最小宽度
        flexWidth = width;
      }
      if (flexWidth > 320) {
        // 设置最大宽度
        flexWidth = 320;
      }
      return flexWidth + "px";
    },
    // renderHeader(createElement, { column }) {
    //   // return createElement(
    //   //   "div",
    //   //   {
    //   //     class: ["thead-cell"],
    //   //     on: {
    //   //       mousedown: ($event) => {
    //   //         this.handleMouseDown($event, column);
    //   //       },
    //   //       mousemove: ($event) => {
    //   //         this.handleMouseMove($event, column);
    //   //       },
    //   //     },
    //   //   },
    //   //   [
    //   //     // 添加 <a> 用于显示表头 label
    //   //     createElement("a", column.label),
    //   //     // 添加一个空标签用于显示拖动动画
    //   //     createElement("span", {
    //   //       class: ["virtual"],
    //   //     }),
    //   //   ]
    //   // );
    // },
    // 按下鼠标开始拖动
    handleMouseDown(e, column) {
      this.dragState.dragging = true;
      this.dragState.start = parseInt(column.columnKey);
      // 给拖动时的虚拟容器添加宽高
      const table = document.getElementsByClassName("table")[0];
      const virtual = document.getElementsByClassName("virtual");
      for (const item of virtual) {
        item.style.height = table.clientHeight - 1 + "px";
        item.style.width = item.parentElement.parentElement.clientWidth + "px";
      }
      document.addEventListener("mouseup", this.handleMouseUp);
    },

    // 鼠标放开结束拖动
    handleMouseUp() {
      this.dragColumn(this.dragState);
      // 初始化拖动状态
      this.dragState = {
        start: -9,
        end: -9,
        dragging: false,
        direction: undefined,
      };
      document.removeEventListener("mouseup", this.handleMouseUp);
    },

    // 拖动中
    handleMouseMove(e, column) {
      if (this.dragState.dragging) {
        const index = parseInt(column.columnKey); // 记录起始列
        if (index - this.dragState.start !== 0) {
          this.dragState.direction =
            index - this.dragState.start < 0 ? "left" : "right"; // 判断拖动方向
          this.dragState.end = index;
        } else {
          this.dragState.direction = undefined;
        }
      } else {
        return false;
      }
    },

    // 拖动易位
    dragColumn({ start, end, direction }) {
      const tempData = [];
      const left = direction === "left";
      const min = left ? end : start - 1;
      const max = left ? start + 1 : end;
      for (let i = 0; i < this.tableHeader.length; i++) {
        if (i === end) {
          tempData.push(this.tableHeader[start]);
        } else if (i > min && i < max) {
          tempData.push(this.tableHeader[left ? i - 1 : i + 1]);
        } else {
          tempData.push(this.tableHeader[i]);
        }
      }
      this.tableHeader = tempData;
    },
    headerCellClassName({ column, columnIndex }) {
      let realColumnIndex = columnIndex;
      if (this.options.rowDrag || this.options.tableExpand)
        realColumnIndex = columnIndex - 1; // 兼容拖拽列
      const active =
        realColumnIndex === this.dragState.end
          ? `darg_active_${this.dragState.direction}`
          : "";
      const start =
        realColumnIndex === this.dragState.start ? `darg_start` : "";
      return `${active} ${start}`;
    },
    cellClassName({ column, columnIndex }) {
      let realColumnIndex = columnIndex;
      if (this.options.rowDrag || this.options.tableExpand)
        realColumnIndex = columnIndex - 1; // 兼容拖拽列
      return realColumnIndex === this.dragState.start ? `darg_start` : "";
    },
    // 列表懒加载,必须开启懒加载
    loadGetData(row, treeNode, resolve) {
      // 懒加载事件数据
      const data = {
        row: row,
        treeNode: treeNode,
        resolve: resolve,
      };
      this.$emit("loadGetData", data);
    },

    /**
     * 当选择项发生变化时会触发该事件
     */
    handleSelectionChange(val) {
      // 多行选中
      this.multipleSelection = val;
      this.$emit("handleSelectionChange", val.length, val);
    },
    /**
     * 单击行事件
     */
    clickRow(row, column, event) {
      // 解决复选框不可点击时，行可以选中的问题
      if (row.isNoChecked) return;
      if (!this.options.multi) {
        // 设置Table 选择模式 只能单选或者多选
        this.$refs.multipleTable.clearSelection();
        this.$refs.multipleTable.toggleRowSelection(row);
      } else {
        this.$refs.multipleTable.toggleRowSelection(row);
      }
      // this.getIndex = row.id

      const data = {
        row: row,
        column: column,
        event: event,
      };
      this.$emit("clickRow", row);
    },
    /**
     * 用户手动勾选复选框触发
     */
    select(sel, row) {
      // if (!this.options.multi) {
      //   // 设置Table 选择模式 只能单选或者多选

      //   this.$refs.multipleTable.toggleRowSelection(row)
      // }
      // todo: 代码为什么这么写，我也不知道
      if (!this.options.multi) {
        if (sel.length > 1) {
          const del_row = sel.shift();
          this.$refs.multipleTable.toggleRowSelection(del_row, false);
        }
      }

      const data = {
        sel: sel,
        row: row,
      };
      this.$emit("clickRow", row);
      this.$emit("select", data);
    },
    /**
     * 双击行事件
     */
    dblclickRow(row, column, event) {
      const data = {
        row: row,
        column: column,
        event: event,
      };
      this.$emit("dblclickRow", data);
    },
    handleCellStyle({ row, column, rowIndex, columnIndex }) {
      const baseStyle = { padding: "0px" };

      let mergedObj;
      let dynamicStyle = false;
      if (
        this.options.cellStyleChangeList &&
        this.options.cellStyleChangeList.length > 0
      ) {
        if (this.options.cellStyleChangeList.includes(column.property)) {
          const currentColumn = this.tableHeader.find(
            (t) => t.field === column.property
          );
          if (currentColumn && currentColumn.tableCellStyle) {
            // if()
            currentColumn.tableCellStyle.forEach((c) => {
              if (c.value === row[currentColumn.field]) {
                dynamicStyle = true;
                mergedObj = { ...baseStyle, ...c.style };
              }
            });
          }
        }
      }
      return dynamicStyle ? mergedObj : baseStyle;
    },
    /**
     * @description: 展开行
     * @param {*} row
     */
    expandRow(row) {
      this.$emit("expandRow", row);
    },
    /**
     * 右键行事件-没有去掉页面默认
     */
    contextmenu(row, column, event) {
      const data = {
        row: row,
        column: column,
        event: event,
      };
      this.$emit("contextmenu", data);
    },

    /**
     * 头部列点击事件
     */
    headClick(column, event) {
      const data = {
        column: column,
        event: event,
      };
      this.$emit("headClick", data);
    },
    /**
     * 头部列右击点击事件
     */
    headcontextmenu(column, event) {
      const data = {
        column: column,
        event: event,
      };
      this.$emit("headcontextmenu", data);
    },
    /**
     * 当前行发生改变时的事件
     */
    rowChange(currentRow, oldCurrentRow) {
      const data = {
        currentRow: currentRow,
        oldCurrentRow: oldCurrentRow,
      };
      this.$emit("rowChange", data);
    },

    /**
     * 用户点击全选触发
     */
    selectAll(sel) {
      const data = {
        sel: sel,
      };
      this.$emit("selectAll", data);
    },
    openMenu(e) {
      this.currentCellText = e.srcElement.innerText; // 单元格
      this.left = e.x;
      this.top = e.y;

      this.visible = true;
    },
    closeMenu() {
      this.visible = false;
    },
    exportExcel() {
      import("@/vendor/Export2Excel").then((excel) => {
        // const tHeader = this.columns.map(item => item.field).filter(item => item !== undefined)
        const tHeader = this.columns
          .map((item) => item.label)
          .filter((item) => item !== undefined);
        const filterVal = [];
        this.columns.forEach((c) => {
          if (c.field !== undefined) {
            filterVal.push({
              field: c.field,
              filterOptions: c.filterOptions,
              isItemValue: c.isItemValue,
            });
          }
        });
        const list = this.list;
        const data = this.formatJson(filterVal, list);
        excel.export_json_to_excel({
          header: tHeader,
          data,
          filename: "excel-list",
          bookType: "xlsx",
        });
      });
    },
    formatJson(filterVal, jsonData) {
      return jsonData.map((v) =>
        filterVal.map((j) => {
          if (j.field === "timestamp") {
            return parseTime(v[j]);
          } else if (j.filterOptions && j.filterOptions.length > 0) {
            if (j.isItemValue) {
              const valInfo = j.filterOptions.find(
                (f) => f.itemKey === v[j.field]
              );
              if (valInfo) {
                return valInfo.itemValue;
              } else {
                return null;
              }
            } else {
              const valInfo = j.filterOptions.find(
                (f) => f.label === v[j.field]
              );
              if (valInfo) {
                return valInfo.value;
              } else {
                return null;
              }
            }
          } else {
            return v[j.field];
          }
        })
      );
    },
    // 初始化table
    onClearSelection() {
      this.$refs.refTable.clearSelection();
    },
    // 该方法获取初始值的时候会有多次点击的问题

    cellClick(row, column, cell, event) {
      // 不可点击时return

      if (row.isNoChecked) return;
      if (
        this.cellClickIndex !== row.id ||
        this.cellClickLabel !== column.label
      ) {
        this.tempRow = row[column.property];
      }
      this.cellClickIndex = row.id;
      this.cellField = column.property;
      this.cellClickLabel = column.label;

      // 由于InputNumber的引入,点击值得触发机制有问题
    },
    // 失去焦点函数(待用)
    inputBlur(callback, row) {
      this.cellClickIndex = null;
      this.cellClickLabel = "";
      callback && callback(row);
    },
    async saveRow(scope, callback, value) {
      this.cellClickIndex = null;
      this.cellClickLabel = "";
      // console.log(this.cellField, this.cellField, '---saveRow----')
      try {
        await callback(scope.row);
        // this.$message.success('保存成功')
      } catch (err) {
        scope.row[this.cellField] = this.tempRow;

        // this.$message.error(err)
      }
    },
    async switchChange(scope, callback, value) {
      // this.cellClickIndex = null
      // this.cellClickLabel = ''
      console.log(scope, callback, value, "---saveRow----");
      try {
        await callback(scope.row);
        // this.$message.success('保存成功')
      } catch (err) {
        console.log("🚀 ~ switchChange ~ err:", err);

        // this.$message.error(err)
      }
    },

    async blurRow(scope, callback) {
      console.log("🚀 ~ blurRow ~ scope, callback:失去焦点", scope, callback);
      this.cellClickIndex = null;
      this.cellClickLabel = "";
      try {
        await callback(scope.row);
        // this.$message.success('保存成功')
      } catch (err) {
        scope.row[this.cellField] = this.tempRow;

        // this.$message.error(err)
      }
    },
    async inputNumberChange(scope, inputChange) {
      // this.cellClickLabel = ''
      // console.log(this.cellField, this.cellField, '---saveRow----')
      try {
        await inputChange(scope.row);
        // this.$message.success('保存成功')
      } catch (err) {
        scope.row[this.cellField] = this.tempRow;

        // this.$message.error(err)
      }
    },
    inputNumberMaxValFun(scope, maxValFun) {
      return maxValFun(scope.row);
    },
    clearRow(scope) {
      this.cellClickIndex = null;
      this.cellClickLabel = "";
      scope.row[this.cellField] = this.tempRow;
    },
    // selectedstyle({ row, rowIndex }) {
    //   if ((this.getIndex) === row.id) {
    //     return {
    //       'background-color': 'red'
    //     }
    //   } else {
    //     return { height: 35 + 'px' }
    //   }
    // }
    // todo: 暂时不用我没有理解
    setSort() {
      const el = this.$refs.multipleTable.$el.querySelectorAll(
        ".el-table__body-wrapper > table > tbody"
      )[0];
      this.sortable = Sortable.create(el, {
        ghostClass: "sortable-ghost", // Class name for the drop placeholder,
        handle: ".drag-handler",
        setData: function (dataTransfer) {
          // to avoid Firefox bug
          // Detail see : https://github.com/RubaXa/Sortable/issues/1012
          dataTransfer.setData("Text", "");
        },
        onEnd: (evt) => {
          this.oldList = [...this.list];
          const targetRow = this.list.splice(evt.oldIndex, 1)[0];
          this.list.splice(evt.newIndex, 0, targetRow);
          this.newList = [...this.list];
          this.$emit("rowDrag", this.oldList, this.newList);
          // // for show the changes, you can delete in you code
          // const tempIndex = this.newList.splice(evt.oldIndex, 1)[0]
          // this.newList.splice(evt.newIndex, 0, tempIndex)
        },
      });
    },
    // 勾选数据行的 Checkbox 时触发的事件
    rowClass({ row, rowIndex }) {
      row.$index = rowIndex;

      if (this.options.rowBgcFields) {
        if (row[this.options.rowBgcFields]) {
          if (this.selectRow.includes(rowIndex)) {
            return "selectRowColor";
          } else {
            return "bgcHighlight";
          }
        } else {
          if (this.selectRow.includes(rowIndex)) {
            return "selectRowColor";
          } else {
            return this.tableRowClass(row, rowIndex);
          }
        }
      } else {
        if (this.selectRow.includes(rowIndex)) {
          return "selectRowColor";
        } else {
          return this.tableRowClass(row, rowIndex);
        }
      }
    },
    getSummaries(param) {
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "汇总";
          return;
        }
        const sum = this.columns
          .filter((item) => item.field === column.property)
          .map((item) => item.sum)[0];
        const values = data.map((item) => Number(item[column.property]));
        if (sum) {
          if (!values.every((value) => isNaN(value))) {
            sums[index] = values.reduce((prev, curr) => {
              const value = Number(curr);
              if (!isNaN(value)) {
                return prev + curr;
              } else {
                return prev;
              }
            }, 0);
            // 添加后缀
            // sums[index] += ''
          } else {
            sums[index] = "-";
          }
        } else {
          sums[index] = "-";
        }
      });

      return sums;
    },
    /**
     * @description: 多选下单元格显示用,隔开的字符串
     * @param {*} options
     * @param {*} value
     */
    transform(options, value) {
      let showValue = "";
      value.forEach((item, index) => {
        if (index === value.length - 1) {
          showValue += options
            .filter((item1) => item1.value === item)
            .map((item1) => item1.label);
        } else {
          const labelList = options
            .filter((item1) => item1.value === item)
            .map((item1) => item1.label);
          if (labelList.length > 0) {
            showValue += labelList + ";";
          }
        }
      });
      return showValue;
    },
    /**
     * @description: 下拉框隐藏时触发
     * @param {*} isMultiple 是否多选
     * @param {*} callback 回调
     * @param {*} row 当前行
     */
    chooseCustom(e, isMultiple, callback, row) {
      if (!e && isMultiple) {
        setTimeout(() => {
          this.inputBlur(callback, row);
        }, 50);
      }
    },

    selectChange(column, row) {
      if (column.notShowSave) {
        this.cellClickIndex = null;
        this.cellClickLabel = "";
      }
      if (!this.options.multi) {
        // 设置Table 选择模式 只能单选或者多选
        this.$refs.multipleTable.clearSelection();
        this.$refs.multipleTable.toggleRowSelection(row, true);
      } else {
        this.$refs.multipleTable.toggleRowSelection(row, true);
      }
    },
    /**
     * @description: 复制单元格数据
     */
    copyCurrentCell() {
      const aux = document.createElement("input");
      aux.setAttribute("value", this.currentCellText);
      document.body.appendChild(aux);
      aux.select();
      document.execCommand("copy");
      document.body.removeChild(aux);
      if (document.execCommand("copy")) {
        this.$message.success("单元格内容复制成功");
      } else {
        this.$message.error("单元格内容复制失败");
      }
    },
    /**
     * @description: 合并相同行
     * @param {*} row
     * @param {*} column
     * @param {*} rowIndex
     * @param {*} columnIndex
     */
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      let startIndex = 0;
      if (this.tableHeader[0].type === "selection") {
        startIndex = 1;
      }
      if (columnIndex === startIndex) {
        const dataProvider = this.list;
        const cellValue = row[column.property];

        if (cellValue) {
          const prevRow = dataProvider[rowIndex - 1];
          let nextRow = dataProvider[rowIndex + 1];
          if (prevRow && prevRow[column.property] === cellValue) {
            return { rowspan: 0, colspan: 0 };
          } else {
            let rowspan = 1;
            while (nextRow && nextRow[column.property] === cellValue) {
              rowspan++;
              nextRow = dataProvider[rowspan + rowIndex];
            }
            if (rowspan > 1) {
              return { rowspan, colspan: 1 };
            }
          }
        }
      }
    },
    handleSortChange({ column, prop, order }) {
      this.selectRow = [];
      this.list.sort((a, b) => {
        if (order === "ascending") {
          return a[prop] > b[prop] ? 1 : -1;
        } else if (order === "descending") {
          return a[prop] < b[prop] ? 1 : -1;
        }
        return 0;
      });
      if (this.multipleSelection.length > 0) {
        this.multipleSelection.forEach((item, index) => {
          this.selectRow.push(this.list.indexOf(item));
        });
      }
    },
    /**
     * @description: 打开文件
     * @param {*} files
     */
    openFilePreviewPage(files) {
      const copyFile = [];
      files.forEach((e) => {
        const ext = e.url.substr(e.url.lastIndexOf(".") + 1);
        copyFile.push({ url: e.url, fileType: ext });
      });
      // 在新页面打开
      const routeData = this.$router.resolve({
        path: "/filePreviewPage",
        query: {
          dataList: JSON.stringify(copyFile).replace(/%/g, "%25"), // 防止数据中有%
        },
      });
      window.open(routeData.href, "_blank");
    },
  },
};
</script>

<style>
.sortable-ghost {
  opacity: 0.8;
  color: #fff !important;
  background: #42b983 !important;
}
</style>

<style lang="scss" scoped>
.icon-star {
  margin-right: 2px;
}
.drag-handler {
  width: 20px;
  height: 20px;
  cursor: pointer;
}
.show-d {
  margin-top: 15px;
}

.contextClickmenu {
  margin: 0;
  background: #fff;
  z-index: 9999;
  position: fixed;
  list-style-type: none;
  padding: 5px 0;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 400;
  color: #333;
  box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
  li {
    margin: 0;
    padding: 7px 16px;
    cursor: pointer;
    &:hover {
      background: #eee;
    }
  }
}
.table {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: auto;
}
// .table ::v-deep .el-table .el-table__header-wrapper {
//   position: sticky;
//   top: 0;
//   z-index: 100; /* 确保表头在最上层 */
// }
.table ::v-deep .el-table__row td p {
  margin: 0px;
}
.table ::v-deep .el-table th > .cell {
  white-space: nowrap;
}
// 这个先隐藏
// .table ::v-deep .el-table__header-wrapper .el-checkbox {
//   display: none;
// }
// table表头
::v-deep .has-gutter tr th {
  padding: 0;
  background-color: #f7f8fc;
  line-height: 34px;
}
// 当设置fixed 时候出现得table表头
::v-deep .el-table__fixed-header-wrapper tr th {
  padding: 0;
  background-color: #f7f8fc;
  line-height: 34px;
}
//todo: 暂时这么改
.header-ellipsis {
  height: 30px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
::v-deep .el-table .selectRowColor td {
  background: #e6f5f5 !important;
}
::v-deep .el-table .bgcHighlight td {
  background: #f8cdcd !important;
}

// ::v-deep .el-table tbody tr:hover > td {
//   background-color: #ecf5f9 !important;
// }
.editBox {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.table ::v-deep {
  .el-table .darg_start {
    background-color: #f3f3f3 !important;
  }
  .el-table th {
    padding: 0;
    .virtual {
      position: fixed;
      display: block;
      width: 0;
      height: 0;
      margin-left: -10px;
      background: none;
      border: none;
    }
    &.darg_active_left {
      .virtual {
        border-left: 2px dotted #666;
        z-index: 99;
      }
    }
    &.darg_active_right {
      .virtual {
        border-right: 2px dotted #666;
        z-index: 99;
      }
    }
  }
  .thead-cell {
    padding: 0;
    display: inline-flex;
    flex-direction: column;
    align-items: left;
    cursor: pointer;
    overflow: initial;
    &:before {
      content: "";
      position: absolute;
      top: 0;
      left: 20%;
      bottom: 0;
      right: 20%;
    }
  }
}
.table_moving ::v-deep {
  .el-table th .thead-cell {
    cursor: move !important;
  }
  .el-table__fixed {
    cursor: not-allowed;
  }
}
.imgPopover {
  height: 100px !important;
  overflow: auto;
  background: red;
}
.pdfBox {
  height: 500px;
  overflow: auto;
}
.excelClass {
  height: 600px;
  overflow: auto;
  padding-top: 20px;
}
</style>
